#pragma once
#include <cstdio>

class ConsoleLogger {
public:
  ConsoleLogger() = default;
  ConsoleLogger(ConsoleLogger &&) = default;
  ConsoleLogger(const ConsoleLogger &) = default;
  ConsoleLogger &operator=(ConsoleLogger &&) = default;
  ConsoleLogger &operator=(const ConsoleLogger &) = default;
  ~ConsoleLogger() = default;

public:
  void logTransfer(long from, long to, double amount) {
    printf("%ld -> %ld: %f\n", from, to, amount);
  }
};

class FileLogger {
public:
  FileLogger() = default;
  FileLogger(FileLogger &&) = default;
  FileLogger(const FileLogger &) = default;
  FileLogger &operator=(FileLogger &&) = default;
  FileLogger &operator=(const FileLogger &) = default;
  ~FileLogger() = default;

public:
  void logTransfer(long from, long to, double amount) {
    // --snip--
    printf("[file] %ld -> %ld: %f\n", from, to, amount);
  }
};

enum class LoggerType { Console, File };

class Bank {
  ConsoleLogger consoleLogger_;
  FileLogger fileLogger_;
  LoggerType loggerType_ = LoggerType::Console;

public:
  Bank() : consoleLogger_{} {}
  Bank(Bank &&) = default;
  Bank(const Bank &) = default;
  Bank &operator=(Bank &&) = default;
  Bank &operator=(const Bank &) = default;
  ~Bank() = default;

public:
  void setLoggerType(LoggerType loggerType) { loggerType_ = loggerType; }
  void makeTransfer(long from, long to, double amount) {
    // --snip--
    switch (loggerType_) {
      using enum LoggerType;
    case Console: {
      consoleLogger_.logTransfer(from, to, amount);
    } break;
    case File: {
      fileLogger_.logTransfer(from, to, amount);
    } break;
    default:
      break;
    }
  }
};
